package log

import (
	"context"
	"gitee.com/kristas/booting-go/framework/core/bean"
	"gitee.com/kristas/booting-go/framework/core/statement/types"
	"runtime"
	"time"
)

type LoggerFactoryAdapter interface {
	GetLogger() (Logger, error)
}

type Logger interface {
	bean.Bean
	Context(ctx context.Context) Logger
	GetName() string
	Trace(format string, a ...interface{})
	Debug(format string, a ...interface{})
	Info(format string, a ...interface{})
	Warn(format string, a ...interface{})
	Error(format string, a ...interface{})
	Panic(format string, a ...interface{})
	Fatal(format string, a ...interface{})
}

type LoggerAdapter interface {
	bean.Bean
	Trace(a string, meta *Meta)
	Debug(a string, meta *Meta)
	Info(a string, meta *Meta)
	Warn(a string, meta *Meta)
	Error(a string, meta *Meta)
	Panic(a string, meta *Meta)
	Fatal(a string, meta *Meta)
}

type Level int

const (
	Trace Level = iota
	Debug
	Info
	Warn
	Error
	Panic
	Fatal
)

func (l Level) String() string {
	switch l {
	case Trace:
		return "trace"
	case Debug:
		return "debug"
	case Info:
		return "info"
	case Warn:
		return "warn"
	case Error:
		return "error"
	case Panic:
		return "panic"
	case Fatal:
		return "fatal"
	default:
		return "not support"
	}
}

type Configure struct {
	types.AutoConfigure `prefix:"application.logging"`
	Level               string     `json:"level" yaml:"level"`
	Adapter             string     `json:"adapter" yaml:"adapter"`
	SkipIndex           int        `json:"skip_index" yaml:"skip_index"`
	Style               *Style     `json:"style" yaml:"style"`
	Loggers             []*Loggers `json:"loggers" yaml:"loggers"`
}

type Style struct {
	Spec     map[string]*Spec `json:"spec" yaml:"spec"`
	Template []string         `json:"template" yaml:"template"`
}

type Spec struct {
	Layout string `json:"layout" yaml:"layout"`
	Color  int
}

type Loggers struct {
	Name  string `json:"name" yaml:"name"`
	Level string `json:"level" yaml:"level"`
}

const (
	timestamp = "timestamp"
	level     = "level"
	function  = "function"
	location  = "location"
	separator = "separator"
	message   = "message"
)

type Meta struct {
	Ctx       context.Context
	Frame     *runtime.Frame
	Level     Level
	Timestamp time.Time
}
